package cate.game.fight.task;

import cate.common.table.d.GDFunc;
import cate.game.GameBody;
import cate.game.fight.FightTaskContext;
import cate.game.fight.msg.FightPlayResp;
import cate.game.framework.ModuleMan;
import cate.game.play.proce.play.PlayPO;
import cate.game.role.Role;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class FightTaskHandler extends ModuleMan {
    private List<FightTask> tasks = new LinkedList<>();
    public int getTaskSize() {
        return tasks.size();
    }

    /**
     * 任务锁
     */
    private final Lock tasksLock = new ReentrantLock(true);


    @Override
    public void initIndependent(GameBody game) throws Exception {
        super.initIndependent(game);
    }

    @Override
    public void initDependent() throws Exception {

    }

    public void createFightTask(Role role, FightTaskContext context, PlayPO playPO, String uid) {
        FightTask task = new FightTask(game, context, playPO, uid);
        if (context.skip) {
            task.handleResultSelfThread(role);
            return;
        }
        tasksLock.lock();
        try {
            tasks.add(task);
        } catch (Exception e) {
            log.error("", e);
        } finally {
            tasksLock.unlock();
        }
        if (context.needSend && role != null) {
            role.sendNow(new FightPlayResp(context.funcId, playPO));
        }
    }

    /**
     * 检查战斗任务完成情况
     */
    public void checkTask() {
        List<FightTask> handleList = new ArrayList<>();
        tasksLock.lock();
        try {
            Iterator<FightTask> iterator = tasks.iterator();
            while (iterator.hasNext()) {
                FightTask task = iterator.next();
                if (task == null) {
                    iterator.remove();
                    continue;
                }
                boolean justDoIt = false;
                if (task.canAutoFinish()) {
                    if (task.allowHandle(null, false, false)) {
                        justDoIt = true;
                    }
                }
                if (task.isFinishedWhatever()) {
                    justDoIt = true;
                }
                if (justDoIt) {
                    handleList.add(task);
                    iterator.remove();
                }
            }
        } catch (Exception e) {
            log.error("", e);
        } finally {
            tasksLock.unlock();
        }
        for (FightTask task : handleList) {
            task.handleResult(null);
        }
    }

    /**
     * 获取任务
     */
    public FightTask getTask(Role role, int funcId) {
        tasksLock.lock();
        try {
            Iterator<FightTask> iterator = tasks.iterator();
            while (iterator.hasNext()) {
                FightTask task = iterator.next();
                if (task.belong(role, funcId)) {
                    return task;
                }
            }
            return null;
        } catch (Exception e) {
            log.error("", e);
            return null;
        } finally {
            tasksLock.unlock();
        }
    }

    /**
     * 移除任务
     */
    public FightTask removeTask(Role role, int funcId) {
        tasksLock.lock();
        try {
            Iterator<FightTask> iterator = tasks.iterator();
            while (iterator.hasNext()) {
                FightTask task = iterator.next();
                if (task.belong(role, funcId)) {
                    iterator.remove();
                    return task;
                }
            }
            return null;
        } catch (Exception e) {
            log.error("", e);
            return null;
        } finally {
            tasksLock.unlock();
        }
    }

    /**
     * 强制结算战斗结果
     *
     * @param skip 跳过战斗
     */
    public void handleResultForce(Role role, int funcId, boolean skip) {
        List<FightTask> handleList = new ArrayList<>();
        tasksLock.lock();
        try {
            Iterator<FightTask> iterator = tasks.iterator();
            while (iterator.hasNext()) {
                FightTask task = iterator.next();
                if (task.belong(role, funcId)) {
                    if (task.allowHandle(role, skip, true)) {
                        handleList.add(task);
                        iterator.remove();
                    } else {
                        game.notice.message(role, "英雄调息中...稍等片刻");
                    }
                }
            }
        } catch (Exception e) {
            log.error("", e);
        } finally {
            tasksLock.unlock();
        }

        for (FightTask task : handleList) {
            try {
                task.handleResult(role);
            } catch (Exception e) {
                log.error("", e);
            }
        }
    }

    /**
     * 手动处理结果（客户端发起的请求）
     *
     * @param skip 跳过战斗
     */
    public void handleResultManually(Role role, int funcId, boolean skip) {
        if (skip) {
            if (funcId == GDFunc.POINT_RACE) {
                if (!role.getPvp().pointRace.canSkip()) {
                    role.getGame().notice.message(role, "无法跳过资格赛");
                    return;
                }
            }
        }
        handleResultForce(role, funcId, skip);
    }

    @Override
    public void shutdown() {
        tasksLock.lock();
        try {
            // 之所以要拷贝出来执行，是因为比如无尽试炼会自动再添加战斗任务，就钻了可重入锁的空子，因为是在同一线程中发生的事情
            List<FightTask> handleList = new ArrayList<>();
            handleList.addAll(tasks);
            for (FightTask task : handleList) {
                task.handleResult(null);
            }
            tasks.clear();
        } catch (Exception e) {
            log.error("结束全部任务的时候，出现了异常", e);
        } finally {
            tasksLock.unlock();
        }
    }
}
